﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace MoneyBook.Windows {
    
    public class WeakEventListener<TInstance, TEventArgs> : WeakEventListener<TInstance, object, TEventArgs>
        where TInstance : class
        where TEventArgs : EventArgs {

        public WeakEventListener(TInstance instance,
            Action<TInstance, object, TEventArgs> eventAction,
            Action<WeakEventListener<TInstance, object, TEventArgs>> detachAction)
            : base(instance, eventAction, detachAction) {

        }
    }

    public class WeakEventListener<TInstance, TSource, TEventArgs>
        where TInstance : class
        where TEventArgs : EventArgs {

        private WeakReference weakInstance;

        private Action<TInstance, TSource, TEventArgs> OnEventAction { get; set; }

        private Action<WeakEventListener<TInstance, TSource, TEventArgs>> OnDetachAction { get; set; }

        public WeakEventListener(TInstance instance,
            Action<TInstance, TSource, TEventArgs> eventAction,
            Action<WeakEventListener<TInstance, TSource, TEventArgs>> detachAction) {

            if (instance == null) throw new ArgumentNullException("instance");
            if (eventAction == null) throw new ArgumentNullException("eventAction");
            if (detachAction == null) throw new ArgumentNullException("detachAction");

            weakInstance = new WeakReference(instance);

            this.OnEventAction = eventAction;
            this.OnDetachAction = detachAction;
        }

        public void OnEvent(TSource source, TEventArgs eventArgs) {
            TInstance target = (TInstance)weakInstance.Target;
            if (null != target) {
                if (null != OnEventAction) {
                    OnEventAction(target, source, eventArgs);
                }
            } else {
                Detach();
            }
        }

        public void Detach() {
            if (null != OnDetachAction) {
                OnDetachAction(this);
                OnDetachAction = null;
            }
        }
    }
}
